package ch.quantasy.android.repetitive.implementation;

import java.util.HashMap;
import java.util.concurrent.TimeUnit;

import ch.quantasy.android.repetitive.definition.RepeaterAction;
import ch.quantasy.android.repetitive.definition.RepeaterStrategy;

/**
 * This class serves as facade in order to process repetitive tasks. There are
 * different strategies for repetition, some are accurate or fast but cost
 * energy, some are not as accurate or slow but preserve energy.
 * 
 * 
 * @author quantasy
 * 
 */
public class RepetitiveContextFacade {
	private static final String TAG = "RepetitiveContextFacade";

	private static final String STRATEGY_SLEEP = "sleep";
	private static final String STRATEGY_ARLARM_RTC = "alarm_rtc";
	private final HashMap<String, RepeaterStrategy> repeaterStrategies;
	private String activeStrategy;
	private final RepeaterAction repeaterAction;

	public RepetitiveContextFacade(final RepeaterAction repeaterAction) {
		this.repeaterAction = repeaterAction;
		this.repeaterStrategies = new HashMap<String, RepeaterStrategy>();
		this.repeaterStrategies.put(
				RepetitiveContextFacade.STRATEGY_ARLARM_RTC,
				new AlarmRepeaterStrategy(repeaterAction));
		this.repeaterStrategies.put(RepetitiveContextFacade.STRATEGY_SLEEP,
				new SleepRepeaterStrategy(repeaterAction));
		this.activeStrategy = RepetitiveContextFacade.STRATEGY_SLEEP;
	}

	public boolean isRunning() {
		return this.repeaterStrategies.get(this.activeStrategy).isRunning();
	}

	/**
	 * Start repeating the action- after the time specified
	 */
	public void startTimedRepetition() {
		WakeLockManager.setup(this.repeaterAction.getContext());
		try {
			WakeLockManager.s_acquire();
			new Thread() {
				@Override
				public void run() {
					try {
						WakeLockManager.s_acquire();
						RepetitiveContextFacade.this.repeaterAction.onRepeat();
					} finally {
						WakeLockManager.s_release();
					}

				}
			}.start();
		} finally {
			WakeLockManager.s_release();
		}
	}

	/**
	 * Stop repeating the action.
	 */
	public void stopTimedRepetition() {
		this.repeaterStrategies.get(this.activeStrategy).stopTimedRepetition();
	}

	public void setUpdateInterval(final long updateInterval, final TimeUnit unit) {
		final RepeaterStrategy active = this.repeaterStrategies
				.get(this.activeStrategy);
		if ((active != null)
				&& (active.getUpdateIntervalInMillis() == unit
						.toSeconds(updateInterval))) {
			return;
		}
		String activating = null;
		if (unit.toSeconds(updateInterval) < 10) {
			activating = RepetitiveContextFacade.STRATEGY_SLEEP;
		} else {
			activating = RepetitiveContextFacade.STRATEGY_ARLARM_RTC;
		}
		this.repeaterStrategies.get(activating).setUpdateInterval(
				active.getLatestRepetitionInMillis(), updateInterval, unit);

		if (!active.equals(this.repeaterStrategies.get(activating))) {
			if (this.repeaterStrategies.get(this.activeStrategy).isRunning()) {
				this.repeaterStrategies.get(this.activeStrategy)
						.stopTimedRepetition();
				this.repeaterStrategies.get(activating).startTimedRepetition();
			}
			this.activeStrategy = activating;
		}

	}

	public long getUpdateIntervalInMillis() {
		return this.repeaterStrategies.get(this.activeStrategy)
				.getUpdateIntervalInMillis();
	}

	@Override
	public void finalize() {
		for (final RepeaterStrategy strategy : this.repeaterStrategies.values()) {
			strategy.finalize();
		}
	}

}
